package cn.fnst.facecomp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.Date;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;

import org.apache.axis.Constants;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.message.MessageElement;
import org.apache.axis.types.Schema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import cn.com.softwise.face360.FaceContrast;
import cn.fnst.facecomp.dao.CommonDao;
import cn.fnst.facecomp.model.ComparePhotoInfo;
import cn.fnst.facecomp.model.PhotoDate;
import cn.fnst.facecomp.service.GetPhotoService;
import cn.fnst.facecomp.utils.Utils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * Servlet implementation class ImgContrast
 */
public class ImgContrast extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	protected Logger log = LoggerFactory.getLogger(getClass());
	private CommonDao commonDao;
	private GetPhotoService gps = new GetPhotoService();
	
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ImgContrast() {
        super();
        try {
			commonDao = CommonDao.getInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String pic1 = request.getParameter("pic1");
		String idCard = request.getParameter("idCard");
		String userCard = request.getParameter("userCard");
		String error = null;
		
		log.info("pic1: " + pic1);
		log.info("idCard: " + idCard);
		log.info("userCard: " + userCard);
		
		if(userCard != null){
			userCard = userCard.toUpperCase();
		}
		if(idCard != null){
			idCard = idCard.toUpperCase();
		}
		
		if(!Utils.isIdCorrect(idCard)){
			error = "输入的身份证号非法";
			request.setAttribute("error", error);
			request.setAttribute("pic1", pic1);
			request.setAttribute("idCard", idCard);
			request.setAttribute("userCard", userCard);
			request.getRequestDispatcher(Constant.PAGE_INDEX).forward(request, response);
			return;
		}
		
		try{
			if(userCard != null){
				long times = commonDao.getUsedTimes(userCard, Utils.getDateString(new Date()));
				log.info("已使用次数: " + times);
				
				if( times >= Constant.MAX_TIMES){
					error = "今日试用次数过多,请改天再试.";
					request.setAttribute("error", error);
					request.setAttribute("pic1", pic1);
					request.setAttribute("idCard", idCard);
					request.getRequestDispatcher(Constant.PAGE_INDEX).forward(request, response);
					return;
				}
			}	
		}catch(Exception e){
			log.error("统计用户使用次数失败", e);
		}
		
		ComparePhotoInfo c = new ComparePhotoInfo();
		c.setUploadTime(Utils.getTimeString(new Date()));
		c.setId(Long.valueOf(pic1.substring(pic1.lastIndexOf("_")+1, pic1.lastIndexOf("."))));
		c.setUserIdentityCard(userCard);
		c.setCompareIdentityCard(idCard);
		
		String daySuffix = Utils.getDateString(new Date()) + "/";		
		
		String idCardPicName1 = getSavePath1(daySuffix) + c.getCompareIdentityCard() + "_" + c.getId() + "_A.jpg";
		String idCardPicName2 = getSavePath2(daySuffix) + c.getCompareIdentityCard() + "_" + c.getId() + "_B.jpg";
		
		//获取证件照片
		
		long t1 = System.currentTimeMillis();
		
		PhotoDate photoDate = gps.execute(idCard);

		String pic2A = photoDate.getPhoto1DateStr();		
		String pic2B = photoDate.getPhoto2DateStr();
		
		long t2 = System.currentTimeMillis();
		
		savePicture(pic2A, idCardPicName1);
		savePicture(pic2B, idCardPicName2);
		
		long t3 = System.currentTimeMillis();
		
		if (pic2A == null && pic2B == null) {
			//更新流程日志
			c.setCompareInfo("2");
			commonDao.updateComparePhotoInfo(c);
			
			error = "没有查询到该身份证号码的照片信息。";
			request.setAttribute("error", error);
			request.setAttribute("pic1", pic1);
			request.setAttribute("idCard", idCard);
			request.getRequestDispatcher(Constant.PAGE_INDEX).forward(request, response);
			return;
		}
		
		log.info("#pic path: " + pic1 );
		//String pic1Base64 = getBase64ByFilename(pic1, daySuffix);
		String pic1Base64 = getBase64ByFilename(pic1, "");
		String result1 = "0";
		String result2 = "0";
		if(pic2A != null){
			result1 = (new FaceContrast()).imgContrast(idCard, pic1Base64, pic2A);
		}		
		
		long t4 = System.currentTimeMillis();
		
		if(pic2B != null){
			result2 = (new FaceContrast()).imgContrast(idCard, pic1Base64, pic2B);
		}
		long t5 = System.currentTimeMillis();
		
		float score1 = 0;
		String error1 = null;
		try {			
			score1 = Float.parseFloat(result1);
		} catch (NumberFormatException e) {
			score1 = -1;
			error1 = result1;
		}
		
		float score2 = 0;
		String error2 = null;
		try {			
			score2 = Float.parseFloat(result2);
		} catch (NumberFormatException e) {
			score2 = -1;
			error2 = result2;
		}
		
		String result = null;
		if (score1 == -1 && score2 == -1) {
			if(error1 != null && error1.trim().length() > 0){
				request.setAttribute("error", error1);
				c.setCompareResult(error1);
			}else{
				request.setAttribute("error", error2);
				c.setCompareResult(error2);
			}
			
			//添加流程日誌
			c.setCompareInfo("3");			
			commonDao.updateComparePhotoInfo(c);
			//返回登录页面
			request.setAttribute("pic1", pic1);
			request.getRequestDispatcher(Constant.PAGE_INDEX).forward(request, response);
			return;
		} else {
			int rate = Math.round(score1 * 100);
			if(score1 < score2){
				rate = Math.round(score2 * 100);
			}
			result = "" + rate;
		}
		request.setAttribute("result", result);
		
		//添加流程日誌		
		c.setCompareResult(result);
		c.setCompareInfo("1");
		try{
			c.setInterfacePhoto(getSavePath1(daySuffix).substring(0, getSavePath1(daySuffix).lastIndexOf("save1/")));
		}catch(Exception e){
			log.error(e.getMessage());
		}
		commonDao.updateComparePhotoInfo(c);
		long t6 = System.currentTimeMillis();
		
		//时间统计
		log.warn("获取证件照片时间," + (t2-t1)/1000.0 + "s " + idCard);
		log.warn("保存证件照片时间," + (t3-t2)/1000.0 + "s " + idCard);
		log.warn("对比身份证照片时间," + (t4-t3)/1000.0 + "s " + idCard);
		log.warn("对比市民卡照片时间," + (t5-t4)/1000.0 + "s " + idCard);
		log.warn("保存流程记录信息时间," + (t6-t5)/1000.0 + "s " + idCard);
		
		//回写分享信息
		setShareInfo(request, c, result, pic1);
		
		request.getRequestDispatcher(Constant.PAGE_RESULT).forward(request, response);
	}
	
	private void setShareInfo(HttpServletRequest request, ComparePhotoInfo c, String result, String pic1){
		try{
			String shareTitle = Constant.SHARE_TITLE;
			String shareDesc1 = Constant.SHARE_DESC1 + result;
			String shareDesc2 = Constant.SHARE_DESC2 + shareTitle;
			
			StringBuilder sb = new StringBuilder();
			sb.append(Constant.SHARE_URL + "?jlwbshare=true");
			sb.append("&img=").append(URLDecoder.decode(Constant.FACE_LOGO, "utf-8"))
			.append("&nullImg=").append(URLDecoder.decode(Constant.FACE_LOGO, "utf-8"))
			.append("&title=").append(URLDecoder.decode(shareTitle, "utf-8"))
			.append("&desc=").append(URLDecoder.decode(shareDesc1, "utf-8")).append("%")
			.append(URLDecoder.decode(shareDesc2, "utf-8"))
			.append("&url=").append(URLDecoder.decode(Constant.SHARE_URL, "utf-8"))
			.append("#");
			
			request.setAttribute("idCard", c.getCompareIdentityCard());
			request.setAttribute("photoUrl", pic1);
			request.setAttribute("iphoneShareInfo", sb.toString());		
			request.setAttribute("id", c.getId()+"");
			
			//回写微信分享信息
			request.setAttribute("shareImg", Constant.FACE_LOGO);
			request.setAttribute("shareNullImg", Constant.FACE_LOGO);
			request.setAttribute("shareTitle", shareTitle);
			request.setAttribute("shareDesc", shareDesc1+"%"+shareDesc2);
			request.setAttribute("shareUrl", Constant.SHARE_URL);
		}catch(Exception e){
			log.error("设置分享信息出错", e);
		}
	}
	
	public String queryPicByIdCard(String idCard) throws Exception {
		String method = "queryExecute";
		String nameSpace = "http://rkk.hoperun.com.cn/DataShareService";
		String serviceUrl = "http://10.250.90.200:8080/RkkService/services/DataShareService_GA";
		Service service = new Service();
		Call call = (Call) service.createCall();
		call.setTimeout(new Integer(3000));
		call.setTargetEndpointAddress(serviceUrl);
		call.setOperation(method);
		call.setUseSOAPAction(true);
		call.setSOAPActionURI(nameSpace + method);
		call.setOperationName(new QName(nameSpace, method));
		call.setReturnClass(org.w3c.dom.Element.class);
		call.setReturnType(XMLType.XSD_SCHEMA);
		call.addParameter("username", Constants.XSD_STRING, ParameterMode.IN);
		call.addParameter("password", Constants.XSD_STRING, ParameterMode.IN);
		call.addParameter("returnColumn", Constants.XSD_STRING, ParameterMode.IN);
		call.addParameter("whereStr", Constants.XSD_STRING, ParameterMode.IN);
		Schema obj = (Schema) call.invoke(new Object[] {"?", "?", "sfzh,xm,xb,mz,zp", "sfzh='"+idCard+"'"});
		MessageElement[] meArray = obj.get_any();
		log.info("obj:" + obj);
		log.info("meArray:" + meArray);
		log.info("meArray length:" + meArray.length);
		if (meArray == null || meArray.length < 3) {
			log.error("没有返回照片信息["+idCard+"]");
			try{
				MessageElement me0 = meArray[0];
				List errorList = me0.getChildren();
				MessageElement mme0 = (MessageElement) errorList.get(1);
				String value = mme0.getValue();
				//System.out.println(value);
				log.error("返回错误信息:" + value);
			}catch(Exception e){
				log.error("照片接口异常", e);
			}
			return null;
		}
		MessageElement me = meArray[2];
		List ll = me.getChildren();
		MessageElement mPic = (MessageElement) ll.get(4);
		return mPic.getValue();
		
	}
	
	public String getBase64ByFilename(String fileName, String daySuffix) {
		File file = new File(getUploadPath(daySuffix) + fileName);;
		FileInputStream inputFile = null;
		byte[] buffer = null;
		try {
			inputFile = new FileInputStream(file);
			buffer = new byte[(int) file.length()];
			inputFile.read(buffer);
			
		} catch (Exception e) {
			log.warn("getBase64ByFilename error: " + daySuffix, e);
		} finally {
			try{
				if(inputFile!=null){ 
					inputFile.close();
				}
			}catch(Exception e){};
		}
		return new BASE64Encoder().encode(buffer);
	}
	
	/*
	public String getUploadPath() {
		String rootPath=getClass().getResource("").getFile().toString();
		return rootPath.substring(0, rootPath.indexOf("WEB-INF")) + "upload/";
	}
	
	
	public String getSavePath1() {
		String rootPath=getClass().getResource("").getFile().toString();
		String path = rootPath.substring(0, rootPath.indexOf("WEB-INF")) + "save1/";
		File file = new File(path);
		if(!file.exists()){
			file.mkdir();
		}
		return path;
	}
	
	public String getSavePath2() {
		String rootPath=getClass().getResource("").getFile().toString();
		String path = rootPath.substring(0, rootPath.indexOf("WEB-INF")) + "save2/";
		File file = new File(path);
		if(!file.exists()){
			file.mkdir();
		}
		return path;
	}*/
	
	protected String getUploadPath(String daySuffix) {
		return getSavePath("upload", daySuffix);
	}
	
	protected String getSavePath1(String daySuffix) {		
		return getSavePath("save1", daySuffix);
	}
	
	protected String getSavePath2(String daySuffix) {		
		return getSavePath("save2", daySuffix);
	}
	
	private String getSavePath(String pathName, String daySuffix){
		String rootPath=getClass().getResource("").getFile().toString();
		String path = rootPath.substring(0, rootPath.indexOf("WEB-INF")) + pathName + "/" + daySuffix;
		File file = new File(path);
		if(!file.exists()){
			file.mkdir();
		}
		return path;
	}
	
	public boolean transport(String imgStr, OutputStream out) {
		if (imgStr == null) // 图像数据为空
			return false;
		BASE64Decoder decoder = new BASE64Decoder();
		try {
			// Base64解码
			byte[] b = decoder.decodeBuffer(imgStr);
			for (int i = 0; i < b.length; ++i) {
				if (b[i] < 0) {// 调整异常数据
					b[i] += 256;
				}
			}
			out.write(b);
			out.flush();
			out.close();
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	
	public void savePicture(String data, String path){
		if(data == null){
			return;
		}
		OutputStream out = null;
		try{
			ByteOutputStream byteOut = new ByteOutputStream();
			transport(data, byteOut);
			byte[] picByte = byteOut.getBytes();			
	        out = new FileOutputStream(path);      
	        out.write(picByte);
	        out.flush();
		}catch(Exception e){
			log.error("保存图片错误["+data+" | " + path + "]", e);
		}finally{
			if(out!=null){
				try{out.close();}catch(Exception e){};
			}
		}
	}
	
}
